#pragma once

#include <windows.h>
#include <fstream>
#include "position.h"

using namespace std;

#define DEFAULT_TRANSPARENCY ' '

struct Map
{
	void gotoxy(int x, int y)
	{
		COORD point = {x, y};
		SetConsoleCursorPosition(
			GetStdHandle(STD_OUTPUT_HANDLE), point);
	}

	// the size of the 2D array
	int width, height, x, y;
	// two dimensional array
	char ** map;

	Map()
		:width(0),height(0),map(0),x(0),y(0)
	{
		//		width = 0;
		//		height = 0;
		//		map = 0;
	}

	// returns false if could not load from file
	bool loadFile(char * filename)
	{
		ifstream fin(filename);
		if(!fin.is_open())
			return false;
		fin >> width;
		fin >> height;
		//printf("the image is %d x %d\n", width, height);
		map = new char * [height];
		for(int i = 0; i < height; i++)
		{
			map[i] = new char [width];
		}
		char input;
		// load the data structure
		for(int y = 0; y < height; ++y)
		{
			for(int x = 0; x < width; ++x)
			{
				input = fin.get();
				if(input == '\n' || input == '\r')
					--x;
				else
					map[y][x] = input;
			}
		}
		fin.close();
		return true;
	}
	~Map()
	{
		if(map)
		{
			for(int i = 0; i < height; i++)
			{
				delete [] map[i];
			}
			delete [] map;
		}
		map = 0;
	}
	// draw Map.map w/ a nested for-loop in the console
	void draw(int a_x, int a_y, int a_background)
	{
		// print the data structure
		for(int y = 0; y < height; ++y)
		{
			for(int x = 0; x < width; ++x)
			{
				gotoxy(a_x+x, a_y+y);
				if(map[y][x] != a_background)
					putchar(map[y][x]);
			}
		}
	}
	void draw(int a_x, int a_y)
	{
		draw(a_x, a_y, DEFAULT_TRANSPARENCY);
	}
	void draw()
	{
		draw(x, y);
	}
	void undraw()
	{
		for (int y = 0; y < height; ++y)
		{
			for (int x = 0; x < width; ++x)
			{
				gotoxy(x, y);
				putchar(' ');
			}
		}
	}
	void drawFlippedH(int a_x, int a_y){
		for(int y = 0; y < height; ++y)
			for(int x = 0; x < width; ++x){
				gotoxy(a_x+x, a_y+y);
				putchar(map[y][(width-1)-x]);	// <--
			}
	}
	void drawFlippedV(int a_x, int a_y){
		for(int y = 0; y < height; ++y)
			for(int x = 0; x < width; ++x){
				gotoxy(a_x+x, a_y+y);
				putchar(map[(height-1)-y][x]);	// <--
			}
	}
	void drawFlippedXY(int a_x, int a_y){
		for(int y = 0; y < width; ++y)			// <--
			for(int x = 0; x < height; ++x){	// <--
				gotoxy(a_x+x, a_y+y);
				putchar(map[x][y]);				// <--
			}
	}
	void drawRotatedCW(int a_x, int a_y){
		for(int y = 0; y < width; ++y)			// <--
			for(int x = 0; x < height; ++x){	// <--
				gotoxy(a_x+x, a_y+y);
				putchar(map[(height-1)-x][y]);	// <--
			}
	}
	void drawRotatedCCW(int a_x, int a_y){
		for(int y = 0; y < width; ++y)			// <--
			for(int x = 0; x < height; ++x){	// <--
				gotoxy(a_x+x, a_y+y);
				putchar(map[x][(width-1)-y]);	// <--
			}
	}
	void flipH(){
		// make the new memory
		char ** temp = new char * [height];
		for(int i = 0; i < height; ++i)	temp[i] = new char[width];
		// set the new memory
		for(int y = 0; y < height; ++y)
			for(int x = 0; x < width; ++x)
				/**/			temp[y][x] = map[y][(width-1)-x];
		// kill the old data
		for(int i = 0; i < height; ++i)	delete [] map[i];
		delete [] map;
		// use the new memory
		map = temp;
	}
	void flipV(){
		// make the new memory
		char ** temp = new char * [height];
		for(int i = 0; i < height; ++i)	temp[i] = new char[width];
		// set the new memory
		for(int y = 0; y < height; ++y)
			for(int x = 0; x < width; ++x)
				/**/			temp[y][x] = map[(height-1)-y][x];
		// kill the old data
		for(int i = 0; i < height; ++i)	delete [] map[i];
		delete [] map;
		// use the new memory
		map = temp;
	}
	void flipXY(){
		// make the new memory
		/**/	char ** temp = new char * [width];
		/**/	for(int i = 0; i < width; ++i)	temp[i] = new char[height];
		// set the new memory
		for(int y = 0; y < height; ++y)
			for(int x = 0; x < width; ++x)
				/**/			temp[x][y] = map[y][x];
		// kill the old data
		for(int i = 0; i < height; ++i)	delete [] map[i];
		delete [] map;
		// use the new memory
		map = temp;
		/**/	int t = height;	height = width;	width = t;
	}
	void rotateCW(){	flipXY();	flipV();	}
	void rotateCCW(){	flipXY();	flipH();	}

	char peekCh(Position a_pos);

};
